#ifndef ANALYZER_H
#define ANALYZER_H

#include "constraint_parser.h"
#include "dfs.h"
#include "disjoint_set.h"

namespace mypointsto{

	struct edge_record{
		static disjoint_set s;
		int v_src, v_dst;
		edge_record(int s, int d);
		bool operator < (const edge_record &rhs) const;
	};

	struct strong_component{
		bool no_deref_node;
		int non_deref_v;
		std::set<int> members;
		strong_component();
		strong_component(bool b, int v);
	};

	bool find_vertex_by_id(Graph &g, int id, vertices_range &range);
	void display_graph(Graph &g, std::ostream &out);
	void print_path(std::vector<Vertex>&, Graph &, std::ostream &out);
	bool is_there_path(Vertex, Vertex, std::map<Vertex, Vertex>&, Graph &, std::vector<Vertex>&);
	void shrink_cycle(std::vector<Vertex>&, Graph &, disjoint_set &s);
	void collapse(Vertex v1, Vertex v2, Graph &g, disjoint_set &s);

	int round_up(int n, int base);

	struct analyzer{
		Graph graph;
		constraint_builder *cons_builder;
		work_list wks;
		disjoint_set scc;
		std::vector<std::pair<int, int> >L;
		std::map<int, int> deref_map;//store temporary deref nodes as described in the hybrid algorithm
		std::map<int, int> reverse_deref_map;//the reverse of deref_map
	
		std::set<edge_record> cycle_detect_edges;
		analyzer();
		analyzer(constraint_builder *cb);

		int initialize();
		int initialize_hybrid();
		int init_graph();
		int init_hybrid_graph();
		void analyze(bool lazy);
		void analyze_hybrid();
		void process_base_constraint(int ptr_id, int val_id, bool init);
		void process_simple_constraint(int src, int dst, bool init);
		void process_load_constraint(int addr_id, int val_id, bool init);
		void process_store_constraint(int val_id, int addr_id, bool init);
		void add_deref_vertex(int src, int dst, cons_t type);
		void dump_graph(std::ostream &out);
		void dump_analysis_result(std::ostream &out);

		bool is_deref_vertex(int id);
	};
}
#endif
